package timing.ukulele.seal.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import timing.ukulele.common.data.ResponseData;
import timing.ukulele.data.user.view.UserVO;
import timing.ukulele.facade.user.feign.UserFeignFacade;
import timing.ukulele.seal.dictionary.SealApproveStatusEnum;
import timing.ukulele.seal.persistent.SealApply;
import timing.ukulele.seal.service.SealApplyService;
import timing.ukulele.seal.vo.SealApplyVO;
import timing.ukulele.web.controller.BaseController;

import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/sealApply")
@Slf4j
public class SealApplyController extends BaseController {
    private final SealApplyService applyService;
    private final UserFeignFacade userFeignFacade;

    public SealApplyController(SealApplyService applyService, UserFeignFacade userFeignFacade) {
        this.applyService = applyService;
        this.userFeignFacade = userFeignFacade;
    }

    @PostMapping
    public ResponseData<String> create(@RequestPart("data") SealApplyVO vo,
                                       @RequestPart("pdf") MultipartFile pdf) {
        vo.setStatus((short) 10);
        return applyService.create(vo, pdf);
    }

    @GetMapping
    public ResponseData<SealApplyVO> getById(@RequestParam("id")Long id) {
        SealApply po = applyService.getById(id);
        if (po == null)
            return successResponse();
        SealApplyVO vo = new SealApplyVO();
        BeanUtils.copyProperties(po, vo);
        ResponseData<UserVO> applyUserRes = userFeignFacade.getUserByUserName(po.getCreateBy());
        if(applyUserRes!=null&&applyUserRes.getData()!=null){
            UserVO user = applyUserRes.getData();
            vo.setCreatorName(StringUtils.hasText(user.getName()) ? user.getName() : user.getUsername());
        }
        if(StringUtils.hasText(po.getApprover())){
            ResponseData<UserVO> approvalUserRes = userFeignFacade.getUserByUserName(po.getApprover());
            if(approvalUserRes!=null&&approvalUserRes.getData()!=null){
                UserVO user = approvalUserRes.getData();
                vo.setApproverName(StringUtils.hasText(user.getName()) ? user.getName() : user.getUsername());
            }
        }
        return successResponse(vo);
    }

    @GetMapping("/agreement")
    public void getSealFile(@RequestParam("id")Long id, HttpServletResponse response) {
        applyService.getAgreementFile(id, response);
    }

    @GetMapping("/approval/my/count")
    public ResponseData<Long> getMyApprovalCount(@RequestHeader("X-USER")String username) {
        Long count = this.applyService.lambdaQuery().eq(SealApply::getApprover, username).eq(SealApply::getStatus, 10).count();
        return successResponse(count);
    }

    @GetMapping("/my/page/{current}/{size}")
    public ResponseData<IPage<SealApplyVO>> getApplyPage(@PathVariable(name = "current") int current,
                                                         @PathVariable(name = "size") int size,
                                                         @RequestParam(value = "status", required = false) Short status,
                                                         @RequestHeader("X-USER") String username) {
        if (size == 0) size = 10;
        if (current == 0) current = 1;
        IPage<SealApplyVO> page = this.applyService.getPage(username, null, status, current, size);
        if (page != null && !CollectionUtils.isEmpty(page.getRecords())) {
            List<SealApplyVO> records = page.getRecords();
            for (SealApplyVO vo : records) {
                ResponseData<UserVO> applyUserRes = userFeignFacade.getUserByUserName(vo.getCreator());
                if(applyUserRes!=null&&applyUserRes.getData()!=null){
                    UserVO user = applyUserRes.getData();
                    vo.setCreatorName(StringUtils.hasText(user.getName()) ? user.getName() : user.getUsername());
                }
                if(StringUtils.hasText(vo.getApprover())){
                    ResponseData<UserVO> approvalUserRes = userFeignFacade.getUserByUserName(vo.getApprover());
                    if(approvalUserRes!=null&&approvalUserRes.getData()!=null){
                        UserVO user = approvalUserRes.getData();
                        vo.setApproverName(StringUtils.hasText(user.getName()) ? user.getName() : user.getUsername());
                    }
                }
            }
        }
        return successResponse(page);
    }

    @GetMapping("/approval/page/{current}/{size}")
    public ResponseData<IPage<SealApplyVO>> getApprovalPage(@PathVariable(name = "current") int current,
                                                            @PathVariable(name = "size") int size,
                                                            @RequestParam(value = "status", required = false) Short status,
                                                            @RequestHeader("X-USER") String username) {
        if (size == 0) size = 10;
        if (current == 0) current = 1;
        IPage<SealApplyVO> page = this.applyService.getPage(null, username, status, current, size);
        if (page != null && !CollectionUtils.isEmpty(page.getRecords())) {
            List<SealApplyVO> records = page.getRecords();
            for (SealApplyVO vo : records) {
                ResponseData<UserVO> applyUserRes = userFeignFacade.getUserByUserName(vo.getCreator());
                if(applyUserRes!=null&&applyUserRes.getData()!=null){
                    UserVO user = applyUserRes.getData();
                    vo.setCreatorName(StringUtils.hasText(user.getName()) ? user.getName() : user.getUsername());
                }
                if(StringUtils.hasText(vo.getApprover())){
                    ResponseData<UserVO> approvalUserRes = userFeignFacade.getUserByUserName(vo.getApprover());
                    if(approvalUserRes!=null&&approvalUserRes.getData()!=null){
                        UserVO user = approvalUserRes.getData();
                        vo.setApproverName(StringUtils.hasText(user.getName()) ? user.getName() : user.getUsername());
                    }
                }
            }
        }
        return successResponse(page);
    }

    @PostMapping("/approval")
    public ResponseData<String> approval(@RequestHeader("X-USER") String currentUser, @RequestParam("id") Long applyId, @RequestParam("status") Integer status,
                                         @RequestParam(value = "opinion", required = false) String opinion) {
        if (!(status == 0 || status == 20))
            return paraErrorResponse();
        if (!SealApproveStatusEnum.hasValue(status)) {
            return paraErrorResponse();
        }
        LambdaUpdateChainWrapper<SealApply> updetor = this.applyService.lambdaUpdate()
                .set(SealApply::getStatus, status).set(SealApply::getApproveDate, new Date())
                .set(SealApply::getUpdateBy, currentUser)
                .eq(SealApply::getId, applyId);
        if (StringUtils.hasText(opinion))
            updetor.set(SealApply::getOpinion, opinion);
        updetor.update();
        return successResponse();
    }

    @GetMapping("/unApprovedNumber")
    public ResponseData<Long> unApprovedNumber(@RequestHeader("X-USER") String currentUser) {
        Long count = this.applyService.lambdaQuery()
                .eq(SealApply::getStatus, SealApproveStatusEnum.TO_APPROVE.getCode())
                .eq(SealApply::getCreateBy, currentUser)
                .count();
        return successResponse(count);
    }

    @GetMapping("/toApprovedNumber")
    public ResponseData<Long> toApprovedNumber(@RequestHeader("X-USER") String currentUser) {
        Long count = this.applyService.lambdaQuery()
                .eq(SealApply::getStatus, SealApproveStatusEnum.TO_APPROVE.getCode())
                .eq(SealApply::getApprover, currentUser)
                .count();
        return successResponse(count);
    }
}
